package com.wpen.unit.core.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.wpen.unit.core.ddo.TriggerDo;
import com.wpen.unit.core.service.TaskScheduleHandler;
import com.wpen.unit.core.service.TriggerPoolHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.wpen.unit.infra.mybatis.job.po.LockPo;
import com.wpen.unit.infra.mybatis.job.po.TaskPlanPo;
import com.wpen.unit.infra.repository.job.LockRepository;
import com.wpen.unit.infra.repository.job.TaskPlanRepository;

import lombok.extern.slf4j.Slf4j;

/**
 * 
 * @author Wang Peng
 * @date 2022-12-06
 */
@Service
@Slf4j
public class TaskScheduleHandlerImpl implements TaskScheduleHandler {
    private final static String LOCK_NAME = "unit_job_task_schedule";

    @Autowired
    private LockRepository lockRepository;
    @Autowired
    private TaskPlanRepository taskPlanRepository;
    @Autowired
    private TriggerPoolHelper triggerPoolHelper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void scheduleHandle(String acctDate, long nowTime, int onceSize, long loopReadTime,
            Map<Integer, List<TriggerDo>> delayData) {
        // 锁表
        LockPo lockPo = lockRepository.queryForUpdate(LOCK_NAME);
        if (lockPo == null) {
            lockPo = new LockPo();
            lockPo.setLockName(LOCK_NAME);
            lockRepository.insert(lockPo);
            lockPo = lockRepository.queryForUpdate(LOCK_NAME);
        }
        // 查询
        long queryTime = nowTime + loopReadTime;
        List<TaskPlanPo> taskPlanPos = taskPlanRepository.queryListByNextTime(onceSize, queryTime);
        // 加工处理
        if (taskPlanPos != null && !taskPlanPos.isEmpty()) {
            log.info("Task[" + acctDate + "] delayData>" + delayData.size() + "=" + new Date(queryTime) + ", taskPlan>"
                    + taskPlanPos.size());
            for (TaskPlanPo taskPlanPo : taskPlanPos) {
                // 一条条记录分析
                try {
                    // 直接根据时间判断，到点了就执行
                    TriggerDo triggerDo = new TriggerDo();
                    triggerDo.setAcctDate(acctDate);

                    triggerDo.setBizCode(taskPlanPo.getBizCode());
                    triggerDo.setBatchCode(taskPlanPo.getBatchCode());
                    
                    triggerDo.setTaskCode(taskPlanPo.getTaskCode());
                    triggerDo.setBatchExecLogId(taskPlanPo.getBatchExecLogId());
                    
                    triggerDo.setPlanType(taskPlanPo.getPlanType());
                    triggerDo.setBatchTriggerTime(taskPlanPo.getBatchTriggerTime());
                    triggerDo.setTriggerNextTime(taskPlanPo.getTriggerNextTime());
                    triggerDo.setNowTime(nowTime);

                    if (nowTime >= taskPlanPo.getTriggerNextTime()) {
                        // 如果 任务的执行时间 小于等于 当前时间，，立刻执行
                        log.info("Task[" + taskPlanPo.getBatchCode() + "-" + taskPlanPo.getTaskCode()
                                + "] execute quickly!");
                        // 先按立刻执行处理
                        triggerPoolHelper.triggerTask(triggerDo);
                    } else {
                        // 不到执行时刻点，，延迟执行
                        int delaySecond = (int) ((taskPlanPo.getTriggerNextTime() / 1000) % 60);
                        log.info("Task Add => " + delaySecond + ">" + triggerDo);
                        List<TriggerDo> items = delayData.get(delaySecond);
                        if (items == null) {
                            items = new ArrayList<>();
                            delayData.put(delaySecond, items);
                        }
                        items.add(triggerDo);
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    // TODO 推送日志到监控通知
                }
            }
        }
    }

}
